/*
 *  class IME (Input Method Engine), base class of all InputMethod
 */
function IME() {
    this._context = {
        'input': '',
        'option': '',
        'result': '',
        'currentpage':0
    };
    this.name = 'IME';
    this.pagesize = 10;
    return this;
}

IME.prototype.resetContext = function () {
    this._context['input'] = '';
    this._context['option'] = '';
    this._context['result'] = '',
    this._context['currentpage'] = 0;
}

IME.prototype.getName = function () {   
    return this.name;
};

IME.prototype.getContext = function () {
    return this._context;
}

IME.prototype.processInput = function (s) {
}

// return an array
IME.prototype.getCurrentOption = function () {
    s = this._context['option'].substr(this._context['currentpage']*this.pagesize*2, this.pagesize*2);
    if (s == '') {
        return [];
    }
    if (',' == s[s.length-1]) {
        s = s.substr(0, s.length-1);
    } 
    return s.split(',');   
}

IME.prototype.nextPage = function () {
    total_page = Math.ceil(this._context['option'].length/(this.pagesize*2));
    //console.log(total_page);
    if (this._context['currentpage']+1 < total_page) {
        this._context['currentpage'] += 1;
    }
}

IME.prototype.hasNextPage = function () {
    total_page = Math.ceil(this._context['option'].length/(this.pagesize*2));
    return (this._context['currentpage']+1) < total_page;
}

IME.prototype.previousPage = function () {
    if (this._context['currentpage'] > 0) {
        this._context['currentpage'] -= 1;
    }
}

IME.prototype.hasPreviousPage = function () {
    return this._context['currentpage'] != 0;
}

/*
 *  delete user input. updateContext should be invoked after deleteInput.
 */
IME.prototype.deleteInput = function () {
    //console.log('deleteInput');
    if (this._context['input'].length != 0) {
        this._context['input'] = this._context['input'].substr(0, 
            this._context['input'].length-1);
    }
    this._context['currentpage'] = 0;
}
//  end definition of IME

/*
 *  class StrokeIM
 */
function StrokeIM() {
    this.name = 'StrokeIM';
    this.keytable = {
        button1: 'a',
        button2: 'b',
        button3: 'c',
        button4: 'd',
        button5: 'e',
        button6: undefined,
        button7: undefined,
        button8: undefined,
        button9: undefined,
        button0: undefined,
        buttonstar: undefined,
        buttonwell: undefined
    };
    
    /* get stroketable via AJAX
    $.getScript('/sim/stroketable.js', function () {
        console.log('load ok.'); // stroketable in global namespaces
    });*/
    return this;
}

StrokeIM.prototype = new IME();

/*
 *  eat user input. updateContext should be invoked after processInput.
 */
StrokeIM.prototype.processInput = function (s) {
    // for input
    if (this.keytable[s] != undefined) { 
        this._context['input'] += this.keytable[s];
    }
    this._context['currentpage'] = 0;
}

/*
 *  update StrokeIM context. 
 */
StrokeIM.prototype.updateContext = function () {
    pre_option = this._context['option'];
    this._context['option'] = '';
    if (0 != this._context['input'].length) {
        for (item in stroketable) {
            if (item.indexOf(this._context['input']) == 0) {
                this._context['option'] += stroketable[item]+',';
            }
        }
        
        if (0 == this._context['option'].length) {
            this._context['input'] = this._context['input'].substr(0, 
                this._context['input'].length-1);
            this._context['option'] = pre_option;
        }
    }

}

/*
 *  get input array
 */
StrokeIM.prototype.getInput = function () {
    mapping = {a:'一', b:'丨', c:'丿', d:'丶', e:'乙'};
    ret = new Array();
    for (i=0; i<this._context['input'].length; i++) {
        ret[i] = mapping[this._context['input'][i]];
    }
    return ret;
}
// end definition of StrokeIM

/*
 *  NumberIM
 */
function NumberIM() {
    this.name = 'NumberIM';
    return this
}

NumberIM.prototype = new IME();
// end definition of NumberIM

/*
 *  CharIM
 */
function CharIM() {
    this.name = 'CharIM';
    return this
}

CharIM.prototype = new IME();
// end definition of CharIM

/*
 *  UpperCharIM()
 */
function UpperCharIM() {
    this.name = 'UpperCharIM';
    return this;
}

UpperCharIM.prototype = new IME();
// end definition of UpperCharIM

/*
 *  LowerCharIM
 */ 
function LowerCharIM () {
    this.name = 'LowerCharIM';
    return this;
}

LowerCharIM.prototype = new IME();
// end definition of LowerCharIM
